﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Text;
using System.Web;
using System.Web.UI;
using System.Web.UI.HtmlControls;
using System.Web.UI.WebControls;
using System.Workflow.Activities;
using System.Workflow.Activities.Rules;
using System.Workflow.ComponentModel;
using System.Workflow.ComponentModel.Compiler;
using System.Workflow.ComponentModel.Design;
using System.Workflow.ComponentModel.Serialization;
using System.Workflow.Runtime;
using Ensynch.ILM2.Workflow.Activities;
using Microsoft.IdentityManagement.WebUI;
using Microsoft.IdentityManagement.WebUI.Controls;
using Microsoft.IdentityManagement.WebUI.Controls.Resources;
using Microsoft.ResourceManagement.Utilities;
using Microsoft.ResourceManagement.Workflow.Activities;
using Microsoft.ResourceManagement.WebServices.WSEnumeration;

namespace Ensynch.ILM2.WebUI.Controls
{
    class OwnerRollupActivitySettingsPart : ActivitySettingsPart
    {
        private Table mainTable = new Table();
        FilterBuilder filterBuilder = new FilterBuilder();
        ImageButton moveDownButton = new ImageButton();
        ImageButton moveUpButton = new ImageButton();

        #region Override methods

        protected override void OnLoad(EventArgs e)
        {
            mainTable.Style.Add("background-image",
                Page.ClientScript.GetWebResourceUrl(this.GetType(),
                "Ensynch.ILM2.images.EnsynchWatermark.png"));
            mainTable.Style.Add("background-repeat", "no-repeat");
            mainTable.Style.Add("background-position", "center");
            mainTable.Style.Add("background-size", "100%");
            mainTable.BackColor = Color.White;

            moveDownButton.ImageUrl =
                Page.ClientScript.GetWebResourceUrl(this.GetType(),
                "Ensynch.ILM2.images.movedown.gif");
            moveUpButton.ImageUrl =
                Page.ClientScript.GetWebResourceUrl(this.GetType(),
                "Ensynch.ILM2.images.moveup.gif");

            base.OnLoad(e);
        }

        protected override void CreateChildControls()
        {
            this.InitializeControls();
            base.CreateChildControls();
        }

        public override Activity GenerateActivityOnWorkflow(SequentialWorkflow workflow)
        {
            try
            {
                if (!this.ValidateInputs())
                {
                    return null;
                }
                OwnerRollupActivity activity = new OwnerRollupActivity();

                activity.TheActivityName = getControlText("txtTheActivityName");

                activity.PrimaryOwnerGrammar = getPrimaryOwner();
                activity.BuilderFilter = getBuilderFilter();
                activity.CustomFilter = getControlText("txtCustomFilter");

                return activity;
            }
            catch (Exception ex)
            {
                return null;
            }
        }

        public override void LoadActivitySettings(Activity activity)
        {
            OwnerRollupActivity activity2 = activity as OwnerRollupActivity;
            if (activity2 != null)
            {
                setControlText("txtTheActivityName", activity2.TheActivityName);

                setPrimaryOwner(activity2.PrimaryOwnerGrammar);
                setBuilderFilter(activity2.BuilderFilter);
                setControlText("txtCustomFilter", activity2.CustomFilter);
            }
        }

        public override ActivitySettingsPartData PersistSettings()
        {
            ActivitySettingsPartData data = new ActivitySettingsPartData();

            data["TheActivityName"] = getControlText("txtTheActivityName");

            data["PrimaryOwner"] = getPrimaryOwner();
            data["BuilderFilter"] = getBuilderFilter();
            data["CustomFilter"] = getControlText("txtCustomFilter");
            return data;
        }

        public override void RestoreSettings(ActivitySettingsPartData data)
        {
            if (data != null)
            {
                setControlText("txtTheActivityName", "" + data["TheActivityName"]);

                setPrimaryOwner("" + data["PrimaryOwner"]);
                setBuilderFilter("" + data["BuilderFilter"]);
                setControlText("txtCustomFilter", "" + data["CustomFilter"]);
            }
        }

        public override void SwitchMode(ActivitySettingsPartMode mode)
        {
            bool readOnly = mode != ActivitySettingsPartMode.Edit;
            setControlReadOnly("txtTheActivityName", readOnly);

            setControlReadOnly("txtPrimaryOwner", readOnly);
            filterBuilder.ReadOnly = readOnly;
            moveDownButton.Enabled = !readOnly;
            moveUpButton.Enabled = !readOnly;
            setControlReadOnly("txtCustomFilter", readOnly);
        }

        public override string Title
        {
            get
            {
                string[] tokens = this.GetType().ToString().Split('.');
                return tokens[tokens.Length - 1].Replace("SettingsPart", "") + ": " +
                    getControlText("txtTheActivityName");
            }
        }

        public override bool ValidateInputs()
        {
            bool success = true;

            string primaryOwner = getControlText("txtPrimaryOwner");

            string primaryOwnerErrorSymbols = "";
            string errorMessages = "";
            bool requiresInputMsgShown = false;

            if (primaryOwner.Equals(""))
            {
                primaryOwnerErrorSymbols += "*";
                if (!requiresInputMsgShown)
                {
                    errorMessages += "* <Em>Requires input</Em><br />";
                    requiresInputMsgShown = true;
                }
                success = false;
            }

            setControlText("validatorPrimaryOwner", primaryOwnerErrorSymbols);
            setControlText("validatorMessages", errorMessages);

            return success;
        }

        #endregion

        #region Private methods

        private void InitializeControls()
        {
            string description;
            TableRow tableRow;
            TableCell tableCell;

            mainTable.Width = Unit.Percentage(100.0);
            this.Controls.Add(mainTable);

            //+++ Main Row
            TableRow mainRow = addRowTo(mainTable);
            TableCell mainCell = addCellTo(mainRow);

            Table topTable = new Table();
            topTable.Width = Unit.Percentage(100.0);
            topTable.BorderWidth = 0;
            topTable.CellPadding = 2;
            mainCell.Controls.Add(topTable);

            //--- Table Row
            topTable.Rows.Add(getRow("Activity Name", "",
                "txtTheActivityName", 256, false, "", null));

            //--- Table Row
            topTable.Rows.Add(getPrimaryOwnerRow());

            //--- Table Row
            topTable.Rows.Add(getSectionLine());
            tableRow = addRowTo(topTable);
            tableCell = addCellTo(tableRow);
            tableCell.ColumnSpan = 2;
            Label objectFilterLabel = new Label();
            objectFilterLabel.Text = "Owner Requirements";
            objectFilterLabel.CssClass = base.LabelCssClass;
            tableCell.Controls.Add(objectFilterLabel);

            description =
                "Use this filter to define the requirements that the primary owner must " +
                "satisfy. Note that the filter must operate on Person objects. The primary " +
                "owner will be selected as the first person to satisfy the requirements, " +
                "in the following order of precedence. " +
                "<ul>" +
                "<li>Primary Owner</li>" +
                "<li>Owner's Manager</li>" +
                "<li>Manager's Manager (recursively)</li>" +
                "</ul>";
            Panel descriptionPanel = new Panel();
            Label descriptionLabel = new Label();
            descriptionLabel.Text = description;
            descriptionPanel.CssClass = base.DescriptionCssClass;
            descriptionPanel.Controls.Add(descriptionLabel);
            tableCell.Controls.Add(descriptionPanel);

            //--- Table Row
            tableRow = addRowTo(topTable);
            tableCell = addCellTo(tableRow);
            tableCell.ColumnSpan = 2;
            filterBuilder = new FilterBuilder();
            Panel filterBuilderPanel = new Panel();
            filterBuilderPanel.CssClass = "uocFilterBuilder";
            filterBuilderPanel.Controls.Add(filterBuilder);
            tableCell.Controls.Add(filterBuilderPanel);

            //--- Table Row
            tableRow = addRowTo(topTable);
            tableCell = addCellTo(tableRow);
            tableCell = addCellTo(tableRow);

            moveDownButton.ToolTip = "Customize filter";
            moveDownButton.Click += new ImageClickEventHandler(moveDownButton_Click);
            tableCell.Controls.Add(moveDownButton);

            tableCell.Controls.Add(new LiteralControl("&nbsp;&nbsp;"));

            moveUpButton.ToolTip = "Try to load customized filter back into builder";
            moveUpButton.Click += new ImageClickEventHandler(moveUpButton_Click);
            tableCell.Controls.Add(moveUpButton);

            //--- Table Row
            description = @"If set, this will override the filter builder.";
            topTable.Rows.Add(getRow("Customized Filter", description,
                "txtCustomFilter", int.MaxValue, true, "", "validatorCustomizedFilter"));

            Label validatorMessages = new Label();
            validatorMessages.CssClass = base.ErrorMessageCssClass;
            validatorMessages.ID = "validatorMessages";
            mainCell.Controls.Add(validatorMessages);
        }

        private void moveUpButton_Click(object sender, ImageClickEventArgs e)
        {
            setBuilderFilter(getControlText("txtCustomFilter"));
        }

        private void moveDownButton_Click(object sender, ImageClickEventArgs e)
        {
            this.setControlText("txtCustomFilter", "");
            string filter = getBuilderFilter();
            if (!string.IsNullOrEmpty(filter))
            {
                this.setControlText("txtCustomFilter", filter);
            }
        }

        private string getBuilderFilter()
        {
            FilterType filter;
            bool success = filterBuilder.TryGetFilter(
                "http://schemas.microsoft.com/2006/11/XPathFilterDialect", out filter);
            if (success)
            {
                return filter.Text;
            }
            return "";
        }

        private void setBuilderFilter(string value)
        {
            if (!string.IsNullOrEmpty(value))
            {
                FilterType filter = new FilterType();
                filter.Dialect = "http://schemas.microsoft.com/2006/11/XPathFilterDialect";
                filter.Text = value;
                filterBuilder.SetFilter(filter);
            }
        }

        private TableRow getSectionLine()
        {
            TableRow tempRow = new TableRow();
            TableCell tempCell = new TableCell();
            tempRow.Cells.Add(tempCell);
            tempCell.Attributes.Add("class", "ms-sectionline");
            tempCell.Attributes.Add("height", "1");
            tempCell.Attributes.Add("colspan", "2");
            return tempRow;
        }

        private TableRow addRowTo(Table table)
        {
            TableRow tempRow = new TableRow();
            table.Rows.Add(tempRow);
            return tempRow;
        }

        private TableCell addCellTo(TableRow row)
        {
            TableCell tempCell = new TableCell();
            row.Cells.Add(tempCell);
            return tempCell;
        }

        private TableRow getRow(String labelText, string description,
            String controlID, int maxLength, Boolean multiLine, string DefaultValue,
            string validatorId)
        {
            TableRow row = new TableRow();
            row.Attributes.Add("rowType", "attributeInfo");
            TableCell labelCell = new TableCell();
            labelCell.VerticalAlign = VerticalAlign.Top;
            TableCell controlCell = new TableCell();
            //controlCell.VerticalAlign = VerticalAlign.Top;

            // Add the label
            Label olabel = new Label();
            olabel.Text = labelText;
            olabel.CssClass = base.LabelCssClass;
            labelCell.Controls.Add(olabel);

            // Validator characters
            Label validatorLabel = new Label();
            validatorLabel.CssClass = base.ErrorMessageCssClass;
            validatorLabel.ID = validatorId;
            labelCell.Controls.Add(validatorLabel);

            // Description
            Panel descriptionPanel = new Panel();
            Label descriptionLabel = new Label();
            descriptionLabel.Text = description;
            descriptionPanel.CssClass = base.DescriptionCssClass;
            descriptionPanel.Controls.Add(descriptionLabel);
            labelCell.Controls.Add(descriptionPanel);

            // Text box
            TextBox oText = new TextBox();
            oText.ID = controlID;
            oText.CssClass = base.TextBoxCssClass;
            oText.Text = DefaultValue;
            oText.MaxLength = maxLength;
            if (multiLine)
            {
                oText.TextMode = TextBoxMode.MultiLine;
                oText.CssClass = "uocTextBox";
                oText.Rows = 10;
                oText.Columns = 60;
            }
            controlCell.Controls.Add(oText);
            row.Cells.Add(labelCell);
            row.Cells.Add(controlCell);
            return row;
        }

        private TableRow getRow(String labelText, string description,
            List<string> buttonLabels, string buttonListID, int defaultIndex)
        {
            TableRow row = new TableRow();
            row.Attributes.Add("rowType", "attributeInfo");
            TableCell labelCell = new TableCell();
            labelCell.VerticalAlign = VerticalAlign.Top;
            TableCell controlCell = new TableCell();
            //controlCell.VerticalAlign = VerticalAlign.Top;

            // Add the label
            Label olabel = new Label();
            olabel.Text = labelText;
            olabel.CssClass = base.LabelCssClass;
            labelCell.Controls.Add(olabel);

            // Description
            Panel descriptionPanel = new Panel();
            Label descriptionLabel = new Label();
            descriptionLabel.Text = description;
            descriptionPanel.CssClass = base.DescriptionCssClass;
            descriptionPanel.Controls.Add(descriptionLabel);
            labelCell.Controls.Add(descriptionPanel);

            // Radio buttons
            RadioButtonList buttons = new RadioButtonList();
            buttons.ID = buttonListID;
            buttons.CssClass = base.ButtonCssClass;
            for (int i = 0; i < buttonLabels.Count; i++)
            {
                buttons.Items.Add(buttonLabels[i]);
                if (i == defaultIndex)
                {
                    buttons.Items[i].Selected = true;
                }
            }
            controlCell.Controls.Add(buttons);

            row.Cells.Add(labelCell);
            row.Cells.Add(controlCell);
            return row;
        }

        private TableRow getPrimaryOwnerRow()
        {
            String labelText = "Primary Owner";
            string description;
            String controlID = "txtPrimaryOwner";
            int maxLength = 256;
            Boolean multiLine = false;
            string DefaultValue = "";
            string validatorId = "validatorPrimaryOwner";

            description =
@"
Examples:
<ul>
<li>[//Target/DisplayedOwner]</li>
<li>[//Target/Assignee]</li>
</ul>
";

            TableRow row = new TableRow();
            row.Attributes.Add("rowType", "attributeInfo");
            TableCell labelCell = new TableCell();
            labelCell.VerticalAlign = VerticalAlign.Top;
            TableCell controlCell = new TableCell();
            //controlCell.VerticalAlign = VerticalAlign.Top;

            // Add the label
            Label olabel = new Label();
            olabel.Text = labelText;
            olabel.CssClass = base.LabelCssClass;
            labelCell.Controls.Add(olabel);

            // Validator characters
            Label validatorLabel = new Label();
            validatorLabel.CssClass = base.ErrorMessageCssClass;
            validatorLabel.ID = validatorId;
            labelCell.Controls.Add(validatorLabel);

            // Description
            Panel descriptionPanel = new Panel();
            Label descriptionLabel = new Label();
            descriptionLabel.Text = description;
            descriptionPanel.CssClass = base.DescriptionCssClass;
            descriptionPanel.Controls.Add(descriptionLabel);
            labelCell.Controls.Add(descriptionPanel);

            // Text box
            Panel inputPanel = new Panel();
            inputPanel.CssClass = "ms-siteaction ms-vb-tall";
            Label prefixLabel = new Label();
            prefixLabel.Text = "[//Target/";
            prefixLabel.ID = controlID + "Prefix";
            Label suffixLabel = new Label();
            suffixLabel.Text = "]";
            suffixLabel.ID = controlID + "Suffix";
            TextBox oText = new TextBox();
            oText.ID = controlID;
            oText.Style.Add("vertical-align", "middle");
            oText.CssClass = "uocTextBox";
            oText.Text = DefaultValue;
            oText.MaxLength = maxLength;
            oText.Rows = 10;
            if (multiLine)
            {
                oText.TextMode = TextBoxMode.MultiLine;
                oText.CssClass = "uocTextBox";
                oText.Rows = 10;
                oText.Columns = 60;
            }
            inputPanel.Controls.Add(prefixLabel);
            inputPanel.Controls.Add(oText);
            inputPanel.Controls.Add(suffixLabel);

            controlCell.Controls.Add(inputPanel);

            row.Cells.Add(labelCell);
            row.Cells.Add(controlCell);
            return row;
        }

        private void setControlReadOnly(string controlID, Boolean readOnly)
        {
            Control target = this.FindControl(controlID);
            try
            {
                if (target.GetType() == typeof(TextBox))
                {
                    TextBox oText = (TextBox)target;
                    if (oText != null)
                    {
                        oText.ReadOnly = readOnly;
                    }
                    return;
                }
            }
            catch { }
            try
            {
                if (target.GetType() == typeof(RadioButtonList))
                {
                    RadioButtonList buttons = (RadioButtonList)target;
                    if (buttons != null)
                    {
                        buttons.Enabled = !readOnly;
                    }
                    return;
                }
            }
            catch { }
            try
            {
                if (target.GetType() == typeof(DropDownList))
                {
                    DropDownList dropDownList = (DropDownList)target;
                    if (dropDownList != null)
                    {
                        dropDownList.Enabled = !readOnly;
                    }
                    return;
                }
            }
            catch { }
        }

        private string getControlText(string controlID)
        {
            Control target = this.FindControl(controlID);
            try
            {
                if (target.GetType() == typeof(TextBox))
                {
                    TextBox textBox = (TextBox)target;
                    return textBox.Text;
                }
            }
            catch { }
            try
            {
                if (target.GetType() == typeof(Label))
                {
                    Label label = (Label)target;
                    return label.Text;
                }
            }
            catch { }
            try
            {
                if (target.GetType() == typeof(DropDownList))
                {
                    DropDownList dropDown = (DropDownList)target;
                    return dropDown.SelectedValue;
                }
            }
            catch { }
            try
            {
                if (target.GetType() == typeof(RadioButtonList))
                {
                    RadioButtonList buttons = (RadioButtonList)target;
                    return buttons.SelectedValue;
                }
            }
            catch { }
            return "[Control '" + controlID + "' not found]";
        }

        private void setControlText(string controlID, string value)
        {
            Control target = this.FindControl(controlID);
            try
            {
                if (target.GetType() == typeof(TextBox))
                {
                    TextBox textBox = (TextBox)target;
                    textBox.Text = value;
                    return;
                }
            }
            catch { }
            try
            {
                if (target.GetType() == typeof(Label))
                {
                    Label label = (Label)target;
                    label.Text = value;
                    return;
                }
            }
            catch { }
            try
            {
                if (target.GetType() == typeof(DropDownList))
                {
                    DropDownList dropDown = (DropDownList)target;
                    dropDown.SelectedValue = value;
                    return;
                }
            }
            catch { }
            try
            {
                if (target.GetType() == typeof(RadioButtonList))
                {
                    RadioButtonList buttons = (RadioButtonList)target;
                    buttons.SelectedValue = value;
                    return;
                }
            }
            catch { }
        }

        private int getControlIndex(string controlID)
        {
            Control target = this.FindControl(controlID);
            try
            {
                if (target.GetType() == typeof(RadioButtonList))
                {
                    RadioButtonList buttons = (RadioButtonList)target;
                    return buttons.SelectedIndex;
                }
            }
            catch { }
            throw new ArgumentOutOfRangeException("Could not get control index of " + controlID);
        }

        private void setControlIndex(string controlID, int value)
        {
            Control target = this.FindControl(controlID);
            try
            {
                if (target.GetType() == typeof(RadioButtonList))
                {
                    RadioButtonList buttons = (RadioButtonList)target;
                    buttons.SelectedIndex = value;
                    return;
                }
            }
            catch { }
        }

        private bool getControlVisible(string controlID)
        {
            bool visible = true;
            Control target = this.FindControl(controlID);
            if (target != null)
            {
                visible = target.Visible;
            }
            return visible;
        }

        private void setControlVisible(string controlID, Boolean visible)
        {
            Control target = this.FindControl(controlID);
            if (target != null)
            {
                target.Visible = visible;
            }
        }

        private string getPrimaryOwner()
        {
            string result = "[//Target/" +
                getControlText("txtPrimaryOwner") +
                "]";
            return result;
        }

        private void setPrimaryOwner(string input)
        {
            char[] delimiters = { '/' };
            string[] destinationTokens = input
                .Replace('[', delimiters[0]).Replace(']', delimiters[0])
                .Split(delimiters, StringSplitOptions.RemoveEmptyEntries);
            if (destinationTokens != null && destinationTokens.Length > 1)
            {
                setControlText("txtPrimaryOwner", destinationTokens[1]);
            }
        }

        #endregion

    }
}
